package com.eis.persist.dao.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

import com.eis.admin.mvc.bean.BizGroupBean;
import com.eis.persist.dao.UserDAO;
import com.eis.persist.dao.base.BaseDAO;
import com.eis.persist.dao.util.ParentFilerRuleComparator;
import com.eis.persist.dao.util.UserInsertSetter;
import com.eis.persist.model.function.PersistFunctionLayoutGroup;
import com.eis.persist.model.user.PersistBizGroup;
import com.eis.persist.model.user.PersistBizGroupFunction;
import com.eis.persist.model.user.PersistFunctionFilterRule;
import com.eis.persist.model.user.PersistSysGroup;
import com.eis.persist.model.user.PersistUser;
import com.eis.persist.model.user.PersistUserPreferFunction;
import com.eis.util.EncryptUtil;

public class UserDAOImpl extends BaseDAO implements UserDAO {
	private static final Logger logger = LoggerFactory.getLogger(UserDAOImpl.class);
	
	public UserDAOImpl(JdbcTemplate dataSource) {
		
		super(dataSource);
	}
	
	public UserDAOImpl(JdbcTemplate dataSource, String currentUserName) {
		super(dataSource, currentUserName);
	}
	
	@Override
	public boolean userLogon(String userName, String password) {
		// look for the user
		String sql = "select name,password from tb_user where name like ? and disabled=0";
		List<Map<String, Object>> result = dataSource.queryForList(sql, userName);
		
		if (result != null && result.size() > 0) {
			String realPassword = (String)result.get(0).get("password");
			return EncryptUtil.checkPassword(password, realPassword);
		} else {
			return false;
		}
	}

	@Override
	public PersistUser getUserWithConfig(String userName) {
		StringBuilder loaduserAndGroupSqlBuilder 
			= new StringBuilder("select tuser.*,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.id as bizGroupId,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.name as bizGroupName,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.description as bizGroupDescription,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.isConfiged as isConfiged,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.parentId as parentId,");
		loaduserAndGroupSqlBuilder.append("tsysgroup.id as sysGroupId,");
		loaduserAndGroupSqlBuilder.append("tsysgroup.name as sysGroupName,");
		loaduserAndGroupSqlBuilder.append("tsysgroup.description as sysGroupDescription ");
		loaduserAndGroupSqlBuilder.append("from tb_user tuser ");
		loaduserAndGroupSqlBuilder.append("left join tb_bizGroup tbizgroup on tuser.bizGroupId=tbizgroup.id ");
		loaduserAndGroupSqlBuilder.append("left join tb_sysGroup tsysgroup on tuser.sysGroupId=tsysgroup.id ");
		loaduserAndGroupSqlBuilder.append("where tuser.name like ? and tuser.disabled=0");

		List<Map<String, Object>> userAndGroup = dataSource.queryForList(loaduserAndGroupSqlBuilder.toString(), userName);
		PersistUser persistUser = null;
		if (userAndGroup != null && userAndGroup.size() > 0) {
			persistUser = new PersistUser(userAndGroup.get(0));
			
			if (persistUser.getBizGroup() != null) {
				// find biz group parents
				getBizGroupParents(persistUser.getBizGroup()); 
				
				// load group functions and layout
				persistUser.getBizGroup().setGroupFunctions(getBizGroupFunctions(persistUser.getBizGroup()));
				
				// load user functions and layout
				persistUser.setUserPreferFunction(getUserPreferFunctions(persistUser.getId(), persistUser.getBizGroup().getGroupFunctions()));
			}
		}
		
		return persistUser;
	}
	
	public void getBizGroupParents(PersistBizGroup persistBizGroup) {
		List<PersistBizGroup> groupList = getBizGroups();
		Map<Integer, PersistBizGroup> allGroupMap = new HashMap<Integer, PersistBizGroup>();
		for (PersistBizGroup bizGroup : groupList) {
			allGroupMap.put(bizGroup.getId(), bizGroup);
		}
		
		getBizGroupParents(persistBizGroup, allGroupMap);
	}
	
	private void getBizGroupParents(PersistBizGroup persistBizGroup, Map<Integer, PersistBizGroup> allGroupMap) {
		if (persistBizGroup.getParent() != null && persistBizGroup.getParent().getId() > 0) {
				PersistBizGroup parent = allGroupMap.get(persistBizGroup.getParent().getId());
				if (parent != null) {
					persistBizGroup.setParent(parent);
					getBizGroupParents(parent, allGroupMap);
				}
		}
	}
	
	protected List<PersistUserPreferFunction> getUserPreferFunctions(int userId, List<PersistBizGroupFunction> groupFunctions) {
		List<PersistUserPreferFunction> returnList = new ArrayList<PersistUserPreferFunction>();
		if (groupFunctions == null || groupFunctions.size() == 0) return returnList; 
		StringBuilder sqlBuilder = new StringBuilder("select ");
		sqlBuilder.append("userPrefer.id as upid,");
		sqlBuilder.append("userPrefer.bizGroupFunction as bizGroupFunction,");
		sqlBuilder.append("userPrefer.description as upDescription,");
		
		sqlBuilder.append("functionLayout.id as flid,");
		sqlBuilder.append("functionLayout.defaultDisplayname as functionDefaultDisplay,");
		sqlBuilder.append("functionLayout.customizedDisplayName as functionCustomizeDisplay,");
		
		sqlBuilder.append("layoutGroup.id as lgid,");
		sqlBuilder.append("layoutGroup.defaultDisplayname as groupDefaultDisplay,");
		sqlBuilder.append("layoutGroup.customizedDisplayName as groupCustomizeDisplay,");
		sqlBuilder.append("layoutGroup.description as lgDescription, ");
		sqlBuilder.append("layoutGroup.bizsysId as lgbizsysId ");
		
		sqlBuilder.append("from tb_userPreferFunction userPrefer ");
		sqlBuilder.append("inner join tb_bizGroupFunction groupFunction on groupFunction.id=userPrefer.bizGroupFunction ");
		sqlBuilder.append("inner join tb_function tbfunc on groupFunction.functionID=tbfunc.functionId ");
		sqlBuilder.append("left join tb_functionLayout functionLayout on userPrefer.functionLayout=functionLayout.id ");
		sqlBuilder.append("left join tb_layoutGroup layoutGroup on functionLayout.layoutGroupId=layoutGroup.id ");
		sqlBuilder.append("where userPrefer.userId=? and tbfunc.isActive>0");
		
		List<Map<String, Object>> result = dataSource.queryForList(sqlBuilder.toString(), userId);
		
		Map<Integer, PersistBizGroupFunction> groupFunctionMap = new HashMap<Integer, PersistBizGroupFunction>();
		for(PersistBizGroupFunction groupFunction : groupFunctions) {
			groupFunctionMap.put(groupFunction.getId(), groupFunction);
		}
		
		
		if (result != null && result.size() > 0) {
			for (Map<String, Object> oneResult : result) {
				if (groupFunctionMap.get((Integer) oneResult.get("bizGroupFunction")) != null) {
					// check if user can access this function
					PersistFunctionLayoutGroup layoutGroup = new PersistFunctionLayoutGroup(
							(Integer) oneResult.get("lgid"),
							(String) oneResult.get("groupDefaultDisplay"),
							(String) oneResult.get("groupCustomizeDisplay"),
							(String) oneResult.get("lgDescription"),
							(Integer) oneResult.get("lgbizsysId")
							);
					
					com.eis.persist.model.function.PersistFunctionLayout layout = new com.eis.persist.model.function.PersistFunctionLayout(
							(Integer) oneResult.get("flid"),
							(String) oneResult.get("functionDefaultDisplay"),
							(String) oneResult.get("functionCustomizeDisplay"),
							layoutGroup
							);
					
					PersistUserPreferFunction persistUserPreferFunction = new PersistUserPreferFunction(
							(Integer) oneResult.get("upid"),
							userId,
							groupFunctionMap.get((Integer) oneResult.get("bizGroupFunction")),
							(String) oneResult.get("upDescription"),
							layout
							);
					returnList.add(persistUserPreferFunction);
				} else {
					logger.info("illegal access, userid: " + userId + " groupFunctionId: " + (Integer) oneResult.get("bizGroupFunction"));
				}
			}
		}
		
		return returnList;
	}
	
	@Override
	public List<PersistBizGroupFunction> getBizGroupFunctions(PersistBizGroup persistBizGroup) {
		if (persistBizGroup.isConfiged()) {
			StringBuilder sqlBuilder = new StringBuilder("select ");
			sqlBuilder.append("groupFunction.id as gfid,");
			sqlBuilder.append("groupFunction.functionID as functionID,");
			sqlBuilder.append("groupFunction.description as gfDescription,");
			
			sqlBuilder.append("functionLayout.id as flid,");
			sqlBuilder.append("functionLayout.defaultDisplayname as functionDefaultDisplay,");
			sqlBuilder.append("functionLayout.customizedDisplayName as functionCustomizeDisplay,");
			
			sqlBuilder.append("layoutGroup.id as lgid,");
			sqlBuilder.append("layoutGroup.defaultDisplayname as groupDefaultDisplay,");
			sqlBuilder.append("layoutGroup.customizedDisplayName as groupCustomizeDisplay,");
			sqlBuilder.append("layoutGroup.description as lgDescription, ");
			sqlBuilder.append("layoutGroup.bizsysId as lgbizsysId ");
			
			sqlBuilder.append("from tb_bizGroupFunction groupFunction ");
			sqlBuilder.append("inner join tb_function tbfunc on groupFunction.functionID=tbfunc.functionId ");
			sqlBuilder.append("left join tb_functionLayout functionLayout on groupFunction.functionLayout=functionLayout.id ");
			sqlBuilder.append("left join tb_layoutGroup layoutGroup on functionLayout.layoutGroupId=layoutGroup.id ");
			sqlBuilder.append("where groupFunction.bizGroupId=? and tbfunc.isActive>0");
			
			List<Map<String, Object>> result = dataSource.queryForList(sqlBuilder.toString(), persistBizGroup.getId());
			List<PersistBizGroupFunction> returnList = new ArrayList<PersistBizGroupFunction>();
			if (result != null) {
				for (Map<String, Object> oneResult : result) {
					PersistFunctionLayoutGroup layoutGroup = null;
					com.eis.persist.model.function.PersistFunctionLayout layout = null;
					
					if (oneResult.get("lgid") != null) {
						layoutGroup = new PersistFunctionLayoutGroup(
								(Integer) oneResult.get("lgid"),
								(String) oneResult.get("groupDefaultDisplay"),
								(String) oneResult.get("groupCustomizeDisplay"),
								(String) oneResult.get("lgDescription"),
								(Integer) oneResult.get("lgbizsysId")
								);
						layout = new com.eis.persist.model.function.PersistFunctionLayout(
								(Integer) oneResult.get("flid"),
								(String) oneResult.get("functionDefaultDisplay"),
								(String) oneResult.get("functionCustomizeDisplay"),
								layoutGroup
								);
					}
					

					PersistBizGroupFunction groupFunction = new PersistBizGroupFunction(
							(Integer) oneResult.get("gfid"),
							(String) oneResult.get("functionID"),
							(String) oneResult.get("gfDescription"),
							persistBizGroup,
							layout
							);
					
					returnList.add(groupFunction);
				}
			}
			
			return returnList;
		} else if (persistBizGroup.getParent() != null && persistBizGroup.getParent().getId() > 0) {
			// get from parent
			return getBizGroupFunctions(persistBizGroup.getParent());
		} else {
			// an empty list
			return new ArrayList<PersistBizGroupFunction>();
		}
	}

	@Override
	public boolean createUser(PersistUser persistUser) {
		StringBuilder labelBuilder = new StringBuilder("createDate,name,password,email");
		StringBuilder valueBuilder = new StringBuilder("CURRENT_TIMESTAMP,?,?,?");
		if (persistUser.getSysGroup() != null &&  persistUser.getSysGroup().getId() > 0) {
			labelBuilder.append(",sysGroupId");
			valueBuilder.append(",?");
		}
			
		if (persistUser.getBizGroup() != null && persistUser.getBizGroup().getId() > 0) {
			labelBuilder.append(",bizGroupId");
			valueBuilder.append(",?");
		}

		labelBuilder.append(",createBy");
		valueBuilder.append(",?");
		
		String insertSql = "insert into tb_user(" + labelBuilder.toString() 
				+ ") values (" + valueBuilder.toString() + ");";
		
		return dataSource.batchUpdate(insertSql, new UserInsertSetter(persistUser, this.currentUserName)).length == 1;
	}

	@Override
	public List<PersistSysGroup> getSysGroups() {
		String sql = "select * from tb_sysGroup";
		dataSource.queryForList(sql);
		
		List<Map<String, Object>> result = dataSource.queryForList(sql);;
		List<PersistSysGroup> returnList = new ArrayList<PersistSysGroup>();
		if (result != null) {
			for (Map<String, Object> oneResult : result) {
				PersistSysGroup persistSysGroup = new PersistSysGroup(
						(Integer) oneResult.get("id"),
						(String) oneResult.get("name"),
						(String) oneResult.get("description")
						);
				returnList.add(persistSysGroup);
			}
		}
		
		return returnList;
	}

	@Override
	public List<PersistBizGroup> getBizGroups() {
		String sql = "select * from tb_bizgroup order by id";
		dataSource.queryForList(sql);
		
		List<Map<String, Object>> result = dataSource.queryForList(sql);;
		List<PersistBizGroup> returnList = new ArrayList<PersistBizGroup>();
		if (result != null) {
			for (Map<String, Object> oneResult : result) {
				PersistBizGroup persistBizGroup = new PersistBizGroup(
						(Integer) oneResult.get("id"),
						(String) oneResult.get("name"),
						(String) oneResult.get("description"),
						(Integer) oneResult.get("isConfiged") == 1,
						(Integer) (oneResult.get("parentId") != null ? oneResult.get("parentId") : 0)
						);
				returnList.add(persistBizGroup);
			}
		}
		
		return returnList;
	}

	@Override
	public List<PersistUser> getUserForList(PersistUser filter, int pageCount, int pageRows) {
		StringBuilder loaduserAndGroupSqlBuilder = new StringBuilder(
				"select tuser.*,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.id as bizGroupId,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.name as bizGroupName,");
		loaduserAndGroupSqlBuilder.append("tsysgroup.id as sysGroupId,");
		loaduserAndGroupSqlBuilder.append("tsysgroup.name as sysGroupName");
		loaduserAndGroupSqlBuilder.append(" from tb_user tuser ");
		loaduserAndGroupSqlBuilder
				.append("left join tb_bizGroup tbizgroup on tuser.bizGroupId=tbizgroup.id ");
		loaduserAndGroupSqlBuilder
				.append("left join tb_sysGroup tsysgroup on tuser.sysGroupId=tsysgroup.id ");
		loaduserAndGroupSqlBuilder.append("where tuser.disabled=0");
		if (filter != null) {
			if (filter.getName() != null && filter.getName().trim().length() > 0) {
				loaduserAndGroupSqlBuilder.append(" and tuser.name like '%" + filter.getName() + "%'");
			}
			
			if (filter.getSysGroup() != null) {
				if (filter.getSysGroup().getId() > 0) {
					loaduserAndGroupSqlBuilder.append(" and tuser.sysGroupId=" + filter.getSysGroup().getId());
				} else {
					loaduserAndGroupSqlBuilder.append(" and tuser.sysGroupId is null");
				}
			}
			
			if (filter.getBizGroup() != null) {
				if (filter.getBizGroup().getId() > 0) {
					loaduserAndGroupSqlBuilder.append(" and tuser.bizGroupId=" + filter.getBizGroup().getId());
				} else {
					loaduserAndGroupSqlBuilder.append(" and tuser.bizGroupId is null");
				}
			}
		}


		List<Map<String, Object>> userAndGroup = dataSource.queryForList(
				loaduserAndGroupSqlBuilder.toString());
		
		List<PersistUser> resultList = new ArrayList<PersistUser>();
		if (userAndGroup != null && userAndGroup.size() > 0) {
			for (Map<String, Object> oneUser : userAndGroup) {
				PersistUser persistUser = new PersistUser(oneUser);
				resultList.add(persistUser);
			}
			
		}
		return resultList;
	}

	@Override
	public boolean deleteUserById(int userId) {
		
		dataSource.update("delete from tb_userPreferFunction where userid=?", userId);
		int count = dataSource.update("delete from tb_user where id=?", userId);
		
		return count > 0;
	}

	@Override
	public PersistUser getUserForEdit(int userId) {
		StringBuilder loaduserAndGroupSqlBuilder = new StringBuilder("select tuser.*,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.id as bizGroupId,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.name as bizGroupName,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.description as bizGroupDescription,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.isConfiged as isConfiged,");
		loaduserAndGroupSqlBuilder.append("tbizgroup.parentId as parentId,");
		loaduserAndGroupSqlBuilder.append("tsysgroup.id as sysGroupId,");
		loaduserAndGroupSqlBuilder.append("tsysgroup.name as sysGroupName,");
		loaduserAndGroupSqlBuilder.append("tsysgroup.description as sysGroupDescription ");
		loaduserAndGroupSqlBuilder.append("from tb_user tuser ");
		loaduserAndGroupSqlBuilder.append("left join tb_bizGroup tbizgroup on tuser.bizGroupId=tbizgroup.id ");
		loaduserAndGroupSqlBuilder.append("left join tb_sysGroup tsysgroup on tuser.sysGroupId=tsysgroup.id ");
		loaduserAndGroupSqlBuilder.append("where tuser.id=? and tuser.disabled=0");

		List<Map<String, Object>> userAndGroup = dataSource.queryForList(
				loaduserAndGroupSqlBuilder.toString(), userId);
		PersistUser persistUser = null;
		if (userAndGroup != null && userAndGroup.size() > 0) {
			persistUser = new PersistUser(userAndGroup.get(0));
		}

		return persistUser;
	}

	@Override
	public boolean updateUser(PersistUser persistUser) {
		// load the original user
		PersistUser originalUser = getUserForEdit(persistUser.getId());
		if (originalUser != null) {
			StringBuilder sqlBuilder = new StringBuilder("update tb_user set email=?,password=?,sysGroupId=?,bizGroupId=?,updateDate=CURRENT_TIMESTAMP,updatedBy=?");
			sqlBuilder.append(" where id=?");
			
			return dataSource.update(sqlBuilder.toString(), 
					persistUser.getEmail(),
					(persistUser.getPassword() != null && persistUser.getPassword().length() > 0) ? persistUser.getPassword() : originalUser.getPassword(),
					(persistUser.getSysGroup() != null && persistUser.getSysGroup().getId() > 0) ? persistUser.getSysGroup().getId() : null,
					(persistUser.getBizGroup() != null && persistUser.getBizGroup().getId() > 0) ? persistUser.getBizGroup().getId() : null,
					this.currentUserName,
					persistUser.getId()) > 0;
		} else {
			return false;
		}
	}

	@Override
	public List<BizGroupBean> getBizGroupForList(BizGroupBean fliter, int userGroup) {
		List<PersistBizGroup> persistBizGroups =  getBizGroups();
		
		Map<Integer, BizGroupBean> beanmap = new HashMap<Integer, BizGroupBean>();
		List<BizGroupBean> groups = new ArrayList<BizGroupBean>();
		for (PersistBizGroup oneGroup : persistBizGroups) {
			BizGroupBean bean = new BizGroupBean(oneGroup);
			beanmap.put(bean.getId(), bean);

			groups.add(bean);

		}
		
		// get function count
		String sql = "select bizgroup.id,count(groupfunction.id) as count from tb_bizgroup bizgroup " +
				"left join tb_bizGroupFunction groupfunction on bizgroup.id=groupfunction.bizGroupId " +
				"where bizgroup.isConfiged>0 group by bizgroup.id";
		List<Map<String, Object>> countResult = dataSource.queryForList(sql);
		for (Map<String, Object> oneResult : countResult) {
			int id = (Integer) oneResult.get("id");
			
			beanmap.get(id).setFunctionCount(((Long) oneResult.get("count")).intValue());
		}
		
		// setup parent name
		for (int id : beanmap.keySet()) {
			BizGroupBean bean = beanmap.get(id);
			
			BizGroupBean parent = beanmap.get(bean.getParentId());
			if (parent != null) {
				bean.setParentName(parent.getName());
			} else {
				bean.setParentName("");
			}
			
			// customizedParent
			if (bean.getRoot() != 1) {
				BizGroupBean customizedParent = findConfiguredParent(beanmap, bean.getParentId());
				
				if (bean.getCustomized() == 0) {
					bean.setFunctionCount(customizedParent.getFunctionCount());
				}
				bean.setCustomizedParentId(customizedParent.getId());
				bean.setCustomizedParentName(customizedParent.getName());
			}
		}
		
		// just return the user's group and children
		List<BizGroupBean> returnValue = new ArrayList<BizGroupBean>();
		UserFunctionDAOImpl ufd = new UserFunctionDAOImpl(this.dataSource);
		
		List<Integer> childrenIds = new ArrayList<Integer>();
		ufd.getAllChildren(childrenIds, groups, userGroup);
		childrenIds.add(userGroup);
		for (BizGroupBean bean : groups) {
			if (childrenIds.contains(bean.getId())) {
				if (fliter != null && fliter.isFilterable()) {
					if (bean.getName().indexOf(fliter.getName().trim()) >= 0) {
						returnValue.add(bean);
					}
				} else {
					returnValue.add(bean);
				}
			}
		}
		
		return returnValue;
	}
	
	private BizGroupBean findConfiguredParent(Map<Integer, BizGroupBean> beanmap, int parentId) {
		BizGroupBean parent = beanmap.get(parentId);
		if (parent.getCustomized() == 0) {
			return findConfiguredParent(beanmap, parent.getParentId());
		} else {
			return parent;
		}
	}

	@Override
	public boolean createBizGroup(BizGroupBean bizGroup) {
		String sql = "insert into tb_bizGroup(name,description,isConfiged,parentId,createDate,createBy) values (?, ?, 0, ?, CURRENT_TIMESTAMP, ?);";
		
		int result = dataSource.update(sql, bizGroup.getName(), bizGroup.getDescription(), bizGroup.getParentId(), this.currentUserName);
		return result > 0;
	}

	@Override
	public PersistFunctionFilterRule loadFunctionFilterRule(int bizGroupId, String functionId) {
		String sql = "select * from tb_filterrule where bizGroupid=? and functionID=?";
		
		List<Map<String, Object>> result = dataSource.queryForList(sql, bizGroupId, functionId);

		if (result != null && result.size() > 0) {
			PersistFunctionFilterRule persistFunctionFilterRule = new PersistFunctionFilterRule();
			persistFunctionFilterRule.setRulexml((String) result.get(0).get("rulexml"));
			persistFunctionFilterRule.setId((Integer) result.get(0).get("id"));
			persistFunctionFilterRule.setBizGroupid((Integer) result.get(0).get("bizGroupid"));
			persistFunctionFilterRule.setFunctionID((String) result.get(0).get("functionID"));
			persistFunctionFilterRule.setMaxRuleId((Integer) result.get(0).get("maxRuleId"));
			
			return persistFunctionFilterRule;
		} else {
			return null;
		}
	}

	@Override
	public boolean updateFilterRule(int bizGroupId, String functionId, String ruleXml, int maxRuleId) {
		int result;
		if (loadFunctionFilterRule(bizGroupId, functionId) != null) {
			String sql = "update tb_filterrule set ruleXml=?,maxRuleId=?,updatedBy=? where bizGroupid=? and functionID=?";
			result = dataSource.update(sql, ruleXml, maxRuleId, this.currentUserName, bizGroupId, functionId);
		} else {
			String sql = "insert into tb_filterrule(rulexml,bizGroupid,functionID,maxRuleId,createBy,createDate) values(?,?,?,?,?,CURRENT_TIMESTAMP)";
			result =  dataSource.update(sql, ruleXml, bizGroupId, functionId, maxRuleId, this.currentUserName);
		}
		return result > 0;
	}

	@Override
	public PersistBizGroup getBizGroupById(int bizGroupId) {
		String sql = "select * from tb_bizGroup where id=?";
		List<Map<String, Object>> results = this.dataSource.queryForList(sql, bizGroupId);
		if (results.size() > 0) {
			Map<String, Object> result = results.iterator().next();
			PersistBizGroup persistBizGroup = new PersistBizGroup(
					(Integer) result.get("id"),
					(String) result.get("name"),
					(String) result.get("description"),
					(Integer) result.get("isConfiged") == 1,
					(Integer) (result.get("parentId") != null ? result.get("parentId") : 0)
					);
			return persistBizGroup;
		}
		return null;
	}

	@Override
	public List<BizGroupBean> getAllBizGroups() {
		List<PersistBizGroup> persistBizGroups =  getBizGroups();
		
		Map<Integer, BizGroupBean> beanmap = new HashMap<Integer, BizGroupBean>();
		List<BizGroupBean> returnValue = new ArrayList<BizGroupBean>();
		for (PersistBizGroup oneGroup : persistBizGroups) {
			BizGroupBean bean = new BizGroupBean(oneGroup);
			beanmap.put(bean.getId(), bean);
			returnValue.add(bean);
		}
		
		// setup parent name
		for (int id : beanmap.keySet()) {
			BizGroupBean bean = beanmap.get(id);
			
			BizGroupBean parent = beanmap.get(bean.getParentId());
			if (parent != null) {
				bean.setParentName(parent.getName());
			} else {
				bean.setParentName("");
			}
			
			// customizedParent
			if (bean.getRoot() != 1) {
				BizGroupBean customizedParent = findConfiguredParent(beanmap, bean.getParentId());
				
				bean.setFunctionCount(customizedParent.getFunctionCount());
				bean.setCustomizedParentId(customizedParent.getId());
				bean.setCustomizedParentName(customizedParent.getName());
			}
		}
		
		return returnValue;
	}

	@Override
	public List<PersistFunctionFilterRule> loadParentFilterRule(int bizGroupId,
			String functionId, int userBizGroupId) {
		PersistBizGroup childGroup = getBizGroupById(bizGroupId);
		
		this.getBizGroupParents(childGroup);
		
		PersistBizGroup userGroup = getBizGroupById(userBizGroupId);
		this.getBizGroupParents(userGroup);
		Set<Integer> userGroupParentIds = new HashSet<Integer>();
		PersistBizGroup userParent = userGroup.getParent();
		if (userParent != null && userParent.getId() > 0) {
			do {
				userGroupParentIds.add(userParent.getId());
				
				userParent = userParent.getParent();
			} while (userParent != null && userParent.getId() > 0);
		}

		StringBuilder sqlBuilder = new StringBuilder("select * from tb_filterrule where functionID=? and bizGroupid in (");
		
		PersistBizGroup parent = childGroup.getParent();
		Map<Integer, PersistBizGroup> parentMap = new HashMap<Integer, PersistBizGroup>();
		
		List<PersistFunctionFilterRule> parentFilterRules = new ArrayList<PersistFunctionFilterRule>();
		
		if (parent != null && parent.getId() > 0) {
			int order = 0;
			do {
				parentMap.put(parent.getId(), parent);
				parent.setOrder(order);order++;
				if (parent.getParent() == null || parent.getParent().getId() <= 0) {
					// the last one
					sqlBuilder.append(parent.getId());
				} else {
					sqlBuilder.append(parent.getId() + ",");
				}
				parent = parent.getParent();
			}
			while (parent != null && parent.getId() > 0);
			
			sqlBuilder.append(")");

			List<Map<String, Object>> results = dataSource.queryForList(sqlBuilder.toString(), functionId);

			
			if (results != null && results.size() > 0) {
				for (Map<String, Object> result : results) {
					PersistFunctionFilterRule persistFunctionFilterRule = new PersistFunctionFilterRule();
					persistFunctionFilterRule.setRulexml((String) result.get("rulexml"));
					persistFunctionFilterRule.setId((Integer) result.get("id"));
					persistFunctionFilterRule.setBizGroupid((Integer) result.get("bizGroupid"));
					persistFunctionFilterRule.setFunctionID((String) result.get("functionID"));
					persistFunctionFilterRule.setMaxRuleId((Integer) result.get("maxRuleId"));
					persistFunctionFilterRule.setGroupName(parentMap.get(persistFunctionFilterRule.getBizGroupid()).getName());
					
					persistFunctionFilterRule.setEditAble(
							userGroupParentIds.contains(persistFunctionFilterRule.getBizGroupid()) ? 0 : 1);
					
					parentFilterRules.add(persistFunctionFilterRule);
				}
				
				// sort
				Collections.sort(parentFilterRules, new ParentFilerRuleComparator());
			}
		}

		return parentFilterRules;
	}
}
